#include "whttpserver.h"
#include "../cmainframe.h"

#include <wx/url.h>
#include <wx/socket.h>
#ifdef __WXMSW__
#include <winsock2.h>
#else
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#endif

void SetSocketBufferSize(wxSocketBase* socket, int receiveSize, int sendSize)
{
    // 获取底层的 socket 描述符
    int sockfd = socket->GetSocket();

    if (sockfd != -1) {
        // 设置接收缓冲区大小
        setsockopt(sockfd, SOL_SOCKET, SO_RCVBUF,
                   (const char*)&receiveSize, sizeof(receiveSize));

        // 设置发送缓冲区大小
        setsockopt(sockfd, SOL_SOCKET, SO_SNDBUF,
                   (const char*)&sendSize, sizeof(sendSize));
    }
}

// URL解码函数
wxString UrlDecode(const wxString& str)
{
    wxString result;
    size_t len = str.length();

    for (size_t i = 0; i < len; i++)
    {
        if (str[i] == '%' && i + 2 < len)
        {
            wxString hex = str.SubString(i + 1, i + 2);
            unsigned long value;
            if (hex.ToULong(&value, 16))
            {
                result += static_cast<char>(value);
                i += 2;
            }
            else
            {
                result += str[i];
            }
        }
        else if (str[i] == '+')
        {
            result += ' ';
        }
        else
        {
            result += str[i];
        }
    }

    return result;
}

// 根据文件扩展名获取MIME类型
wxString GetMimeType(const wxString& filename)
{
    wxString ext = filename.AfterLast('.').Lower();

    if (ext == wxT("ico")) return wxT("image/x-icon");
    if (ext == wxT("png")) return wxT("image/png");
    if (ext == wxT("jpg") || ext == wxT("jpeg")) return wxT("image/jpeg");
    if (ext == wxT("gif")) return wxT("image/gif");
    if (ext == wxT("css")) return wxT("text/css");
    if (ext == wxT("js")) return wxT("application/javascript");
    if (ext == wxT("html") || ext == wxT("htm")) return wxT("text/html");
    if (ext == wxT("txt")) return wxT("text/plain");
    if (ext == wxT("json")) return wxT("application/json");
    if (ext == wxT("xml")) return wxT("application/xml");
    if (ext == wxT("pdf")) return wxT("application/pdf");

    //return wxT("application/octet-stream");
    return wxT("");
}

WHttpRequest::WHttpRequest(const wxString& rawRequest)
    : m_method(""), m_path(""), m_isValid(false)
{
    ParseRequest(rawRequest);
}

wxString WHttpRequest::GetHeader(const wxString& name) const
{
    auto it = m_headers.find(name.Lower());
    return it != m_headers.end() ? it->second : wxString(wxT(""));
}
wxString WHttpRequest::GetParam(const wxString& name) const
{
    auto it = m_params.find(name);
    return it != m_params.end() ? it->second : wxString(wxT(""));
}

// 判断是否是真正的favicon请求（Accept头包含image/*）
bool WHttpRequest::IsRealFaviconRequest(void) const
{
    wxString accept = GetHeader("Sec-Fetch-Mode").Lower();
    return accept.Contains("navigate");
}

bool WHttpRequest::IsKeepLive(void) const
{
    wxString accept = GetHeader("Connection").Lower();
    return accept.Contains("keep-alive");
}

// 判断是否是页面请求（Accept头包含text/html）
bool WHttpRequest::IsPageRequest() const
{
    wxString accept = GetAcceptHeader().Lower();
    return accept.Contains("text/html") || accept.Contains("application/xhtml+xml");
}

void WHttpRequest::ParseRequest(const wxString& rawRequest)
{
    wxArrayString lines = wxSplit(rawRequest, wxT('\n'));
    if (lines.IsEmpty()) return;

    // 解析请求行
    wxArrayString requestParts = wxSplit(lines[0], wxT(' '));
    if (requestParts.GetCount() < 3) return;

    m_method = requestParts[0].Upper();
    wxString fullPath = requestParts[1];

    // 分离路径和查询参数
    size_t queryPos = fullPath.Find(wxT('?'));
    if (queryPos == wxString::npos)
    {
        m_path = fullPath;
    }
    else
    {
        m_path = fullPath.SubString(0, queryPos - 1);
        wxString queryString = fullPath.SubString(queryPos + 1, fullPath.Length());
        ParseQueryParams(queryString);
    }

    // 解析头部
    size_t i = 1;
    for (; i < lines.GetCount(); i++)
    {
        if (lines[i].Trim().IsEmpty()) break; // 空行表示头部结束

        size_t colonPos = lines[i].Find(wxT(':'));
        if (colonPos != wxString::npos)
        {
            wxString key = lines[i].SubString(0, colonPos - 1).Trim().Lower();
            wxString value = lines[i].SubString(colonPos + 1, lines[i].Length()).Trim();
            m_headers[key] = value;
        }
    }

    // 解析消息体 (如果有)
    i++; // 跳过空行
    for (; i < lines.GetCount(); i++)
    {
        m_body += lines[i];
        if (i < lines.GetCount() - 1) m_body += wxT("\n");
    }

    // 如果是POST请求，解析表单数据
    if (m_method == wxT("POST"))
    {
        wxString contentType = GetHeader(wxT("content-type"));
        if (contentType.Contains(wxT("application/x-www-form-urlencoded")))
        {
            ParseQueryParams(m_body);
        }
    }

    m_isValid = true;
}

void WHttpRequest::ParseQueryParams(const wxString& queryString)
{
    wxArrayString params = wxSplit(queryString, wxT('&'));
    for (const wxString& param : params)
    {
        size_t equalsPos = param.Find(wxT('='));
        if (equalsPos != wxString::npos)
        {
            wxString key = UrlDecode(param.SubString(0, equalsPos - 1));
            wxString value = UrlDecode(param.SubString(equalsPos + 1, param.Length()));
            m_params[key] = value;
        }
        else
        {
            m_params[param] = wxT("");
        }
    }
}

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

WHttpResponse::WHttpResponse()
    : m_statusCode(200), m_statusMessage(wxT("OK")),m_isBinary(false)
{

}

WHttpResponse::~WHttpResponse()
{

}

void WHttpResponse::SetStatus(int code, const wxString& message)
{
    m_statusCode = code;
    m_statusMessage = message;
}

void WHttpResponse::SetHeader(const wxString& name, const wxString& value)
{
    m_headers[name] = value;
}

void WHttpResponse::SetContent(const wxString& content, const wxString& contentType)
{
    m_content = content;
    SetHeader(wxT("Content-Type"), contentType);
    SetHeader(wxT("Content-Length"), wxString::Format(wxT("%zu"), content.utf8_string().length()));
}

void WHttpResponse::SetBinaryContent(const wxMemoryBuffer& content, const wxString& contentType)
{
    m_binaryContent = content;
    m_isBinary = true;
    SetHeader(wxT("Content-Type"), contentType);
    SetHeader(wxT("Content-Length"), wxString::Format(wxT("%zu"), content.GetDataLen()));
}

wxString WHttpResponse::ToString() const
{
    if (m_isBinary) {
        return "[Binary Data]";
    }

    wxString response = wxString::Format(wxT("HTTP/1.1 %d %s\r\n"), m_statusCode, m_statusMessage);

    for (const auto& header : m_headers)
    {
        response += header.first + ": " + header.second + wxT("\r\n");
    }

    response += wxT("\r\n") + m_content;
    return response;
}

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

WHttpServer::WHttpServer()
    : mServerPort(-1),
      mServer(NULL),
      mNetworkFrameManager(NULL)
{
    m_HeartTimeOutTimer = new wxTimer(this, wxID_ANY);
    this->Bind(wxEVT_TIMER, &WHttpServer::OnHeartTimeOutTimer, this);

    this->Bind(wxEVT_SOCKET, &WHttpServer::OnServerEvent, this);
}

WHttpServer::~WHttpServer()
{
    this->Close();

    if(m_HeartTimeOutTimer)
        delete m_HeartTimeOutTimer;
    m_HeartTimeOutTimer = NULL;
}

/// 开始服务器
bool WHttpServer::Open(wxString ip,int port)
{
    if(ip == "" || port <= 0)
        return false;

    mServerIP = ip;
    mServerPort = port;

    if(mServer != NULL)
        this->Close();

    // 创建地址对象
    wxIPV4address addr;
    if (!mServerIP.empty()) {
        addr.Hostname(mServerIP);  // 绑定到指定IP
    } else {
        addr.AnyAddress();   // 如果IP为空，则绑定到所有接口
    }
    addr.Service(mServerPort);      // 设置端口

    // 创建服务器
    mServer = new wxSocketServer(addr, wxSOCKET_WAITALL | wxSOCKET_REUSEADDR);

    if (!mServer->IsOk()) {
        CMainFrame::getSingleton().printlog(LOG_LEVEL_ERROR,
                                            wxString::Format("无法建立http服务器在%s:%d", mServerIP, mServerPort).utf8_string());
        delete mServer;
        mServer = nullptr;
        return false;
    }

    CMainFrame::getSingleton().printlog(LOG_LEVEL_INFO,
                                        wxString::Format(wxT("http服务器启动成功,侦听 %s:%d"),
                                                         mServerIP.empty() ? "0.0.0.0" : mServerIP,
                                                         mServerPort).utf8_string());

    // 设置事件处理
    mServer->SetEventHandler(*this);
    mServer->SetNotify(wxSOCKET_CONNECTION_FLAG);
    mServer->Notify(true);

    if(m_HeartTimeOutTimer)
        m_HeartTimeOutTimer->Start(10000); // 10秒

    return true;
}

/// 关闭服务器
void WHttpServer::Close(void)
{
    {
        std::lock_guard<std::mutex> lock(m_ClientMutex);
        std::map<int,HttpClientInfo>::iterator iter = mClients.begin();
        for(;iter != mClients.end();++iter)
        {
            (*iter).second.client->Close();
            (*iter).second.client->Destroy();
        }
        mClients.clear();
    }

    if (mServer)
    {
        mServer->Close();
        mServer->Destroy();
    }
    mServer = NULL;

    if(m_HeartTimeOutTimer)
    {
        m_HeartTimeOutTimer->Stop();
    }
}

HttpClientInfo* WHttpServer::getHttpClientInfo(wxSocketBase* client)
{
    std::lock_guard<std::mutex> lock(m_ClientMutex);
    std::map<int,HttpClientInfo>::iterator iter = mClients.find(client->GetSocket());
    if(iter != mClients.end())
        return &((*iter).second);

    return NULL;
}

void WHttpServer::OnHeartTimeOutTimer(wxTimerEvent& event)
{
    wxDateTime now = wxDateTime::Now();
    wxTimeSpan timeout(0, 0, 20); // 20秒超时

    std::lock_guard<std::mutex> lock(m_ClientMutex);
    std::map<int,HttpClientInfo>::iterator iter = mClients.begin();
    for(;iter != mClients.end();)
    {
        // 检查是否超时
        if ((now - (*iter).second.lastActiveTime) > timeout)
        {
            CMainFrame::getSingleton().printlog(LOG_LEVEL_INFO,wxString::Format(wxT("http客户端%d已经超时关闭."),(*iter).second.client->GetSocket()).utf8_string());

            (*iter).second.client->Close();
            (*iter).second.client->Destroy();

            iter = mClients.erase(iter);
        }
        else
            ++iter;
    }
}

// 带错误处理的Accept方法
wxSocketBase* WHttpServer::AcceptWithErrorHandling(bool wait)
{
    wxSocketBase* client = nullptr;
    try
    {
        client = mServer->Accept(wait);
        if (!client)
        {
            wxLogError("接受客户端连接失败");
            return nullptr;
        }

        // 检查socket是否有效
        if (!client->IsOk())
        {
            wxLogError("客户端socket无效");
            client->Destroy();
            return nullptr;
        }

        return client;
    }
    catch (const std::exception& e)
    {
        wxLogError("接受连接时发生异常: %s", e.what());
        if (client) client->Destroy();
        return nullptr;
    }
}

// 安全的响应发送方法
bool WHttpServer::SendResponse(wxSocketBase* client, const WHttpResponse& response)
{
    // 构建响应头
    wxString headers = wxString::Format(wxT("HTTP/1.1 %d %s\r\n"),
                                      response.GetStatusCode(),
                                      response.GetStatusMessage());

    for (const auto& header : response.GetHeaders())
    {
        headers += header.first + wxT(": ") + header.second + wxT("\r\n");
    }
    headers += wxT("\r\n");

    wxMemoryBuffer sendBuffer;

    // 先发送响应头
    const std::string headerData = headers.utf8_string();
    size_t headerLength = headerData.length();

    sendBuffer.AppendData((const char*)headerData.c_str(),headerLength);

    // 发送响应体
    if (response.IsBinary())
    {
        // 发送二进制数据
        const wxMemoryBuffer& buffer = response.GetBinaryContent();
        if(!buffer.IsEmpty())
        {
            const char* data = static_cast<const char*>(buffer.GetData());
            size_t dataLength = buffer.GetDataLen();

            sendBuffer.AppendData((const char*)data,dataLength);
        }
    }
    else
    {
        const std::string content = response.GetContent().utf8_string();
        if (!content.empty())
        {
            const char* contentData = content.c_str();
            size_t contentLength = content.length();

            sendBuffer.AppendData((const char*)contentData,contentLength);
        }
    }

    return ClientSendData(client,(const char*)sendBuffer.GetData(),sendBuffer.GetDataLen());
}

/// 客户端发送数据
bool WHttpServer::ClientSendData(wxSocketBase* client,const char* data, unsigned int datalength)
{
    if (!client || !data || datalength == 0) {
        return false;
    }

    if (!client->IsConnected()) {
        wxLogWarning("Attempt to send data to disconnected client");
        return false;
    }

    // 保存原始标志
    //wxSocketFlags originalFlags = client->GetFlags();

    // 设置为非阻塞模式
    //client->SetFlags(wxSOCKET_NONE);
    //client->SetTimeout(1); // 设置短超时

    size_t totalSent = 0;
    wxStopWatch timer;
    bool success = false;

    try {
        while (totalSent < datalength && timer.Time() < 15000) {
            if (!client->IsConnected()) {
                wxLogWarning("Client disconnected during data transmission");
                break;
            }

            client->Write(data + totalSent, datalength - totalSent);

            if (client->Error()) {
                wxSocketError error = client->LastError();

                if (error == wxSOCKET_WOULDBLOCK) {
                    // 在非阻塞模式下这是正常的，等待可写
                    client->WaitForWrite(1, 100);
                    continue;
                }
                else {
                    wxLogError("Socket send error: %d", error);
                    break;
                }
            }

            size_t sent = client->LastCount();
            if (sent > 0) {
                totalSent += sent;
            } else {
                // 没有数据发送，等待后重试
                wxMilliSleep(10);
            }
        }

        success = (totalSent == datalength);
    }
    catch (...) {
        wxLogError("Exception occurred during socket write");
        success = false;
    }

    // 恢复原始标志
    //client->SetFlags(originalFlags);

    return success;
}

void WHttpServer::OnServerEvent(wxSocketEvent& event)
{
    switch(event.GetSocketEvent())
    {
    case wxSOCKET_CONNECTION:
    {
        static wxLongLong lastConnectionTime = 0;
        wxLongLong currentTime = wxGetLocalTimeMillis();

        // 接受新连接
        wxSocketBase* client = this->AcceptWithErrorHandling();
        if (client)
        {
            // 禁用Nagle算法，确保数据立即发送
            int sockfd = client->GetSocket();
            if (sockfd != -1) {
                int flag = 1;
                setsockopt(sockfd, IPPROTO_TCP, TCP_NODELAY, (const char*)&flag, sizeof(flag));
            }

            SetSocketBufferSize(client, 32 * 1024, 32 * 1024);

            // 设置为非阻塞模式
            client->SetFlags(wxSOCKET_NOWAIT);

            // 设置为阻塞模式
            //client->SetFlags(wxSOCKET_BLOCK);
            //client->SetTimeout(5); // 设置超时（秒）

            client->SetEventHandler(*this);
            client->SetNotify(wxSOCKET_INPUT_FLAG | wxSOCKET_LOST_FLAG);
            client->Notify(true);

            // 防止短时间内重复处理同一个连接事件
            if (currentTime - lastConnectionTime < 200) // 200毫秒内不重复处理
            {
                client->Close();
                client->Destroy();
                return;
            }

            {
                std::lock_guard<std::mutex> lock(m_ClientMutex);
                // 存储客户端socket
                mClients[client->GetSocket()] = HttpClientInfo(client,wxDateTime::Now(),"");
            }

            CMainFrame::getSingleton().printlog(LOG_LEVEL_INFO,wxString::Format(wxT("http客户端:%d到达."),client->GetSocket()).utf8_string());
        }

        lastConnectionTime = currentTime;
    }
        break;
    case wxSOCKET_INPUT:
    {
        // 处理客户端输入
        wxSocketBase* client = event.GetSocket();
        if (client)
        {
            HttpClientInfo *decHttpClientInfo = this->getHttpClientInfo(client);
            if(decHttpClientInfo != NULL)
                decHttpClientInfo->lastActiveTime = wxDateTime::Now();

            ProcessClientRequest(client);
        }
    }
        break;
    case wxSOCKET_LOST:
    {
        // 客户端断开连接
        wxSocketBase* client = event.GetSocket();

        CMainFrame::getSingleton().printlog(LOG_LEVEL_INFO,wxString::Format(wxT("http客户端%d主动关闭."),client->GetSocket()).utf8_string());
        this->CloseAndRemoveClient(client,true);
    }
        break;
    default:
        break;
    }
}

void WHttpServer::CloseAndRemoveClient(wxSocketBase* client, bool normalClose)
{
    if(client == NULL)
        return;

    std::lock_guard<std::mutex> lock(m_ClientMutex);
    // 从客户端列表中移除
    std::map<int,HttpClientInfo>::iterator iter = mClients.find(client->GetSocket());
    if(iter != mClients.end())
    {
        (*iter).second.client->Close();
        (*iter).second.client->Destroy();
        mClients.erase(iter);
    }
}

bool WHttpServer::isExistClientHearder(wxString hearder)
{
    std::lock_guard<std::mutex> lock(m_ClientMutex);
    // 从客户端列表中移除
    std::map<int,HttpClientInfo>::iterator iter = mClients.begin();
    for (;iter != mClients.begin(); ++iter)
    {
        if ((*iter).second.hearder == hearder)
            return true;
    }

    return false;
}

void WHttpServer::setClientHearder(wxSocketBase* client,wxString hearder)
{
    if(client == NULL || hearder == "")
        return;

    std::lock_guard<std::mutex> lock(m_ClientMutex);
    // 从客户端列表中移除
    std::map<int,HttpClientInfo>::iterator iter = mClients.find(client->GetSocket());
    if(iter != mClients.end())
        (*iter).second.hearder = hearder;
}

void WHttpServer::ProcessClientRequest(wxSocketBase* client)
{
    // 检查是否有数据可读
    if (!client->IsData())
        return; // 没有数据，直接返回

    // 读取客户端请求
    char buffer[4096];
    client->Read(buffer, sizeof(buffer) - 1);
    size_t bytesRead = client->LastCount();

    if (bytesRead == 0)
        return;

    buffer[bytesRead] = '\0';

    wxString hearder = wxString::FromUTF8((const char*)buffer,bytesRead);

    if(isExistClientHearder(hearder))
        return;

    setClientHearder(client,hearder);

    // 解析HTTP请求
    WHttpRequest request(hearder);

    //if(request.IsRealFaviconRequest())
    //{
        if (request.IsValid())
        {
            // 生成HTTP响应
            WHttpResponse response;
            GenerateHTTPResponse(request, response);

            // 发送响应（使用安全的发送方法）
            SendResponse(client, response);
        }
        else
        {
            WHttpResponse response;
            response.SetStatus(400, wxT("Bad Request"));
            response.SetContent(wxT("<h1>400 Bad Request</h1><p>无效的HTTP请求</p>"));

            // 发送响应（使用安全的发送方法）
            SendResponse(client, response);
        }
    //}

    // 正常处理完成后关闭连接
    if(!request.IsKeepLive())
        this->CloseAndRemoveClient(client, true);
}

void WHttpServer::GenerateHTTPResponse(const WHttpRequest& request, WHttpResponse& response)
{
    //wxString method = request.GetMethod();
    wxString path = request.GetPath();
    //const std::map<wxString, wxString>& params = request.GetAllParams();
    bool isProcessData = false;
    wxString MimeType = GetMimeType(path);

    response.SetHeader(wxT("Connection"), request.IsKeepLive() ? wxT("keep-alive") : wxT("close"));
    response.SetHeader(wxT("Server"), wxT("wxSocketServer/1.0"));

    if(MimeType != wxT(""))
    {
        wxMemoryBuffer decdata = mResourceManager.getFileData(wxString::Format(wxT("%s%s"),mWorkingPath,path));
        if(!decdata.IsEmpty())
        {
            response.SetBinaryContent(decdata,MimeType);
            isProcessData = true;
        }
    }
    else if (path == wxT("/"))
    {
        wxMemoryBuffer decdata = mResourceManager.getFileData(wxString::Format(wxT("%s/index.html"),mWorkingPath));
        if(!decdata.IsEmpty())
        {
            response.SetContent(wxString::FromUTF8((const char*)decdata.GetData(),decdata.GetDataLen()));
            isProcessData = true;
        }
    }

    if(!isProcessData &&
        (mNetworkFrameManager == NULL || !mNetworkFrameManager->OnProcessHttpMessage(request,response)))
    {
        response.SetStatus(404, wxT("Not Found"));
        response.SetContent(wxT("<!DOCTYPE html><html><head><meta charset=\"UTF-8\"><title>404 Not Found</title></head>"
            "<body><h1>404 Not Found</h1>"
            "<p>请求的资源不存在。</p>"
            "<p><a href=\"/\">返回首页</a></p>"
            "</body></html>")
            );
    }
}
